﻿using FreeSql;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LeafCore.Components.Freesql
{
    public static class FreeSqlExtensions
    {
        public static IServiceCollection AddFreeSql(this IServiceCollection services, Action<FreeSqlOptions> options)
        {
            var freeSqlOptions = new FreeSqlOptions();
            options.Invoke(freeSqlOptions);

            if (string.IsNullOrEmpty(freeSqlOptions?.ConnectionString))
            {
                throw new ArgumentNullException(message: "数据库连接字符串为空", null);
            }
            services.AddSingleton(sp =>
            {
                var fsql = new FreeSqlBuilder().UseConnectionString(DataType.MySql, freeSqlOptions.ConnectionString).Build();

                if (freeSqlOptions.IsShowSlowSql)
                {
                    fsql.Aop.CurdAfter += (s, e) =>
                    {
                        //记录慢语句
                        if (e.ElapsedMilliseconds >= freeSqlOptions.MinElapsedMilliseconds)
                        {
                            var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("FreeSql");
                            logger.LogInformation($"SQL慢语句(耗时{e.ElapsedMilliseconds}毫秒)：{e.Sql}");
                        }
#if DEBUG
                        Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff}] {e.Sql}");
#endif
                    };
                }

                if (freeSqlOptions.IsOpenSoftDeletedFilter)
                {
                    fsql.GlobalFilter.Apply<ISoftDelete>("SoftDelete", a => a.IsDeleted == false);
                }
                return fsql;
            });

            //freesq开启仓储事务
            if (freeSqlOptions.IsOpenTransaction)
            {
                services.AddScoped<UnitOfWorkManager>();
            }

            return services;
        }

        private interface ISoftDelete
        {
            bool IsDeleted { get; set; }
        }
    }
}
